package edu.asu.sapa;

import java.lang.reflect.Array;
import java.util.Arrays;

import edu.asu.sapa.ground.State;
import edu.asu.sapa.utils.Priority;
import edu.asu.sapa.utils.PriorityQueue;

//can recycle memory a little bit, if we implement a State.set(State) method
// (copying).  But it can reuse this.* allocated elements, since all States
// are kept memory independent.  (so, like, this.actions.set(index,foo)...
// this.actions.setSize(fooSize)...)
public class StateQ extends PriorityQueue<State, StateQ.Wrapper> {
	public static class Wrapper extends Priority<State> {
		public float priority;
		
		public Wrapper() {
			super();
			priority = 0;
		}
		public Wrapper(State u, float time) {
			super(u);
			this.priority = time;
		}
		public Wrapper clone() {
			return (Wrapper) super.clone();
		}
		public final Wrapper set(State u, float time) {
			this.event = u;
			this.priority = time;
			return this;
		}
		public final int compareTo(Priority<State> w) {
			return compareTo((Wrapper) w);
		}
		public int compareTo(Wrapper w) {
			return (int) (priority - w.priority);
		}		
	}
	
	public StateQ() {
		table = new Wrapper[1024];
	}

	public StateQ(int capacity) {
		table = new Wrapper[capacity];
	}
	
	public StateQ clone() {
		StateQ ret=null;
		try {
			ret = (StateQ) super.clone();
		} catch(Exception e) {
			// assert false;
		}
		
		int s = size;
		Wrapper[] eSrc = table;
		Wrapper[] eDst = new Wrapper[s+1024]; 
		ret.table = eDst;
		ret.size = s;
		for (int i = 0; i < s; ++i) {
			eDst[i] = eSrc[i].clone();
		}	
		
		return ret;
	}

	public final Wrapper newElement() {
		return new Wrapper();
	}
	
	public final boolean add(State s,float f) {
		Wrapper[] evts = table;
		
		int i = size;
		if (i >= evts.length) {
//			i=size-1;
//			if (f > evts[i].priority)
//				return false;
//			else
//				size = i;
			//return false;
			growArray();
			evts = table;
		}
		Wrapper t=null;
		if (evts[i] == null) {
			t = new Wrapper(s,f);
		} else {
			t = evts[i];
			t.set(s,f);
		}
		++size;
		
		int parent;
		Wrapper p;
		for (; (parent = (i - 1) >> 1) >= 0 && t.priority < (p=evts[parent]).priority; i = parent) {
			evts[i] = p;
		}
		evts[i] = t;
		
		return true;	
	}

	public final void growArray() {
		Wrapper[] t = new Wrapper[size<<1];
		System.arraycopy(table,0,t,0,size);
		table = t;
		System.out.println(";;State Queue doubled");
	}

	public Wrapper[] toArray() {
		Wrapper[] ret = new Wrapper[size];
		for (int i=0; i<size; ++i) {
			ret[i] = table[i];
		}
		return ret;
	}

}
